#include <QTextBrowser>
#include <QVBoxLayout>
#include <QFileDialog>
#include <QFile>
#include <QMessageBox>
#include <MessageServices.h>
#include <Configuration.h>
#include "MessageBrowserWindow.h"
#include "MessageBrowser.h"
#include "MessageToolBar.h"

namespace Domy {

MessageBrowserWindow::MessageBrowserWindow(ActionEnableCtrl ctrl, QWidget *parent)
    : DockWidgetInterface(ctrl, parent),
      m_msg_bar(new MessageToolBar(this)),
      m_msg_browser(new MessageBrowser(this))
{
    QVBoxLayout *l = new QVBoxLayout(this);
    l->setMargin(0);
    l->setSpacing(0);
    l->addWidget(m_msg_bar, 0);
    l->addWidget(m_msg_browser, 1);
    this->setLayout(l);

    connect(domy_msg, SIGNAL(signalAppendMessage(MessageType, const QStringList &)),
            this, SLOT(slotOnAppendMessage(MessageType, const QStringList &)));
    connect(m_msg_bar, SIGNAL(signalFind(const QString &, bool, bool)),
            this, SLOT(slotOnFind(const QString &, bool, bool)));
    connect(m_msg_bar, SIGNAL(signalFindNext(const QString &, bool, bool)),
            this, SLOT(slotOnFindNext(const QString &, bool, bool)));
    connect(m_msg_bar, SIGNAL(signalFindPrevious(const QString &, bool, bool)),
            this, SLOT(slotOnFindPrevious(const QString &, bool, bool)));
    connect(m_msg_bar, SIGNAL(signalClearFindResult()),
            this, SLOT(slotOnClearFindResult()));
    connect(m_msg_bar, SIGNAL(signalMsgActionTriggered(QAction *)),
            this, SLOT(slotOnMsgActionTriggered(QAction *)));
    connect(m_msg_browser, &MessageBrowser::signalZoomChanged, [&](int zoom) {
        m_msg_bar->setZoomValueDisplay(zoom);
    });
}

MessageBrowserWindow::~MessageBrowserWindow()
{

}

void MessageBrowserWindow::doAction(ActionKey key)
{
    auto get_find_text = [&]()->QString {

        QString find_text = m_msg_browser->getSelectedText();
        if (find_text.isEmpty()) {
            find_text = m_msg_bar->getFindText();
        }
        else {
            m_msg_bar->setFindText(find_text);
        }
        return find_text;
    };

    switch (key) {
    case ActKey_Copy:
        m_msg_browser->copy();
        break;
    case ActKey_SelectAll:
        m_msg_browser->selectAll();
        break;
    case ActKey_Find:
    {
        QString find_text = get_find_text();
        slotOnFind(find_text, m_msg_bar->isCaseSensitive(), m_msg_bar->isWholeWord());
    }
        break;
    case ActKey_FindNext:
    {
        QString find_text = get_find_text();
        slotOnFindNext(find_text, m_msg_bar->isCaseSensitive(), m_msg_bar->isWholeWord());
    }
        break;
    case ActKey_FindPrev:
    {
        QString find_text = get_find_text();
        slotOnFindPrevious(find_text, m_msg_bar->isCaseSensitive(), m_msg_bar->isWholeWord());
    }
        break;
    default:
        break;
    }
}

QDockWidget *MessageBrowserWindow::createDockWidget()
{
    QDockWidget *dock_widget = new QDockWidget(tr("Message"), parentWidget());
    dock_widget->setObjectName("MessageBrowserWindow");
    dock_widget->setFeatures(dock_widget->features() & ~QDockWidget::DockWidgetFloatable);
    dock_widget->setWidget(this);

    return dock_widget;
}

void MessageBrowserWindow::keyPressEvent(QKeyEvent *event)
{
    if (event->key() == Qt::Key_Escape) {
        m_msg_browser->clearFindResult();
        m_msg_bar->setFindText("");
    }

    QWidget::keyPressEvent(event);
}

void MessageBrowserWindow::slotOnAppendMessage(MessageType type, const QStringList &msg_list)
{
    QString text;
    QColor color;

    for (const QString &msg : msg_list) {
        switch (type) {
        case MsgType_Info:
            text = msg;
            color = Qt::black;
            break;
        case MsgType_Warning:
            text = QString("[Warning]:%1").arg(msg);
            color = QColor(236, 188, 29);
            break;
        case MsgType_Error:
            text = QString("[Error]:%2").arg(msg);
            color = Qt::red;
            break;
        default:
            break;
        }

        text = QString("<span style=\"color:%1;\">%2</span>")
                .arg(color.name(QColor::HexRgb))
                .arg(text);

        m_msg_browser->appendHtml(text);
    }
}

void MessageBrowserWindow::slotOnFind(const QString &text, bool is_case_sensitive, bool is_whole_word)
{
    m_msg_browser->findText(text, is_case_sensitive, is_whole_word);
}

void MessageBrowserWindow::slotOnFindNext(const QString &text, bool is_case_sensitive, bool is_whole_word)
{
    if (!m_msg_browser->findNext(text, is_case_sensitive, is_whole_word)) {
        domy_msg->showStatus(tr("The search result has reached the begin location !"));
        m_msg_browser->findText(text, is_case_sensitive, is_whole_word);
    }
}

void MessageBrowserWindow::slotOnFindPrevious(const QString &text, bool is_case_sensitive, bool is_whole_word)
{
    if (!m_msg_browser->findPrevious(text, is_case_sensitive, is_whole_word)) {
        domy_msg->showStatus(tr("The search result has reached the begin location !"));
    }
}

void MessageBrowserWindow::slotOnClearFindResult()
{
    m_msg_browser->clearFindResult();
}

void MessageBrowserWindow::slotOnMsgActionTriggered(QAction *action)
{
    MessageActionKey key = static_cast<MessageActionKey>(action->data().toInt());
    switch (key) {
    case MsgAct_Export:
    {
        QString file_name = QFileDialog::getSaveFileName(this, tr("Export Message"), domy_config->getLastOpenDirPath(), "*.txt");
        if (!file_name.isEmpty()) {
            QByteArray text = m_msg_browser->toPlainText().toUtf8();
            QFile file(file_name);
            bool suc = false;
            if (file.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
                qint64 len = file.write(text);
                suc = (len == text.length());
                file.close();
            }

            if (suc) {
                QMessageBox::information(this, tr("Export Message"), tr("Export message successfully !"),
                                         QMessageBox::Ok, QMessageBox::Ok);
            }
            else {
                QMessageBox::critical(this, tr("Export Message"), tr("Export message unsuccessfully !"),
                                      QMessageBox::Ok, QMessageBox::Ok);
            }
        }
    }
        break;
    case MsgAct_Clear:
        m_msg_browser->clear();
        break;
    case MsgAct_ZoomIn:
        m_msg_browser->zoomViewIn();
        break;
    case MsgAct_ZoomOut:
        m_msg_browser->zoomViewOut();
        break;
    case MsgAct_ZoomReset:
        m_msg_browser->zoomViewReset();
        break;
    default:
        break;
    }
}

} // namespace Domy
